// OpenTxl-C Version 11 symbol table
// J.R. Cordy, Jan 2023

// Copyright 2023, James R. Cordy and others

// Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
// and associated documentation files (the “Software”), to deal in the Software without restriction, 
// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all copies 
// or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 
// AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// The OpenTxl defined nonterminal symbol table.
// Define and maintain the table of nonterminal symbol grammar tree.
// Not used for the TXL boostrap, which has its own private nonterminal symbol table.

// Modification Log

// v11.0 Initial revision, adapted from OpenTxl 11.0

// I/O, strings, memory allocation, exception handling
#include "support.h"

// Global modules
#include "limits.h"
#include "tokens.h"
#include "trees.h"
#include "idents.h"
#include "errors.h"

// Check interface consistency
#include "symbols.h"

// The TXL program nonterminal symbol table 
// Nonterminal defines are compiled into grammar trees for the defined nonterminal symbols, stored here

array (treePT, symbol_symbols);
int symbol_nSymbols;

// Symbol Table Operations

int symbol_enterSymbol (tokenT partId, enum treeKindT kind)
{
#ifndef NOCOMPILE
    for (int p = 1; p <= symbol_nSymbols; p++) {
        if ((tree_trees[symbol_symbols[p]].name) == partId) {
            return (p);
        }
    }

    if (symbol_nSymbols == maxSymbols) {
        string message;
        stringprintf (message, "Too many defined nonterminal types (> %d)", maxSymbols);
        error ("", message, LIMIT_FATAL, 111);
    }

    symbol_nSymbols++;
    symbol_symbols[symbol_nSymbols] = tree_newTreeInit (kind, partId, partId, 0, nilKid);
    return (symbol_nSymbols);
#else
    return (NOT_FOUND);
#endif
}

int symbol_lookupSymbol (tokenT partId)
{
    // returns NOT_FOUND if symbol is not defined
    for (int p = 1; p <= symbol_nSymbols; p++) {
        if ((tree_trees[symbol_symbols[p]].name) == partId) {
            return (p);
        }
    } 

    return (NOT_FOUND);
}

int symbol_findSymbol (tokenT partId)
{
#ifndef NOCOMPILE
    for (int p = 1; p <= symbol_nSymbols; p++) {
        if ((tree_trees[symbol_symbols[p]].name) == partId) {
            return (p);
        }
    }

    string message, typestring;
    externalType ((* (string *) (ident_idents[partId])), typestring);
    stringprintf (message, "[%s] has not been defined", typestring);
    error ("", message, FATAL, 112);

    return (NOT_FOUND);
#else
    return (NOT_FOUND);
#endif
}

// Intiialization
void symbol (void) {
    // 1-origin [1 .. maxSymbols]
    arrayalloc (maxSymbols + 1, treePT, symbol_symbols);
    symbol_symbols[0] = UNUSED;
    symbol_nSymbols = 0;
}
